#ifndef __QTCH_BYTEARRAY_H__
#define __QTCH_BYTEARRAY_H__

#include <memory>
#include <string>
#include <vector>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>

namespace qtch{

class ByteArray {
public:
    typedef std::shared_ptr<ByteArray> ptr;

    struct Node{
        Node(size_t s);
        Node();
        ~Node();
        char* ptr;
        Node *next;
        size_t size;
    };

    ByteArray(size_t base_size = 4096);
    ~ByteArray();
    void writeFint8(int8_t value);
    void writeFuint8(uint8_t value);
    void writeFint16(int16_t value);
    void writeFuint16(uint16_t value);
    void writeFint32(int32_t value);
    void writeFuint32(uint32_t value);
    void writeFint64(int64_t value);
    void writeFuint64(uint64_t value);
    void writeInt32(int32_t value);
    void writeUint32(uint32_t value);
    void writeInt64(int64_t value);
    void writeUint64(uint64_t value);

    void writeFloat(float value);
    void writeDouble(double value);
    void writeStringF16(const std::string& value);
    void writeStringF32(const std::string& value);
    void writeStringF64(const std::string& value);
    void writeStringVint(const std::string& value);
    void writeStringWithoutLength(const std::string& value);


    int8_t readFint8();
    uint8_t readFuint8();
    int16_t readFint16();
    uint16_t readFuint16();
    int32_t readFint32();
    uint32_t readFuint32();
    int64_t readFint64();
    uint64_t readFuint64();
    int32_t readInt32();
    uint32_t readUint32();
    int64_t readInt64();
    uint64_t readUint64();

    float readFloat();
    double readDouble();
    std::string readStringF16();
    std::string readStringF32();
    std::string readStringF64();
    std::string readStringVint();

    void clear();
    void clearUnused();
    void write(const void* buffer, size_t size);
    void read(void* buf, size_t size);
    void read(void* buf, size_t size, size_t position) const;


    size_t getReadPosition() const {return m_readPosition;}
    size_t getWritePosition() const {return m_writePosition;}
    size_t getBaseSize() const {return m_baseSize;}
    size_t getReadSize() const {return m_writePosition - m_readPosition;}


    void setReadPosition(size_t v);
    void setWritePosition(size_t v);
    bool readFromFile(const std::string& name);
    bool writeToFile(const std::string& name);
    bool isLittleEndian() const;
    void setIsLittleEndian(bool v);
    /**
     * @brief 将ByteArray数据[m_readPosition,m_writePosition)数据转化成std::string;
     * 
     */
    std::string toString() const;
    std::string toHexString() const;
    uint64_t getReadBuffer(std::vector<iovec>& buffer, uint64_t len = ~0ull) const;
    uint64_t getReadBuffer(std::vector<iovec>& buffer, uint64_t len, uint64_t position) const;

    /**
     * @brief 获取可写入的缓存,保存成iovec数组
     * @param[out] buffers 保存可写入的内存的iovec数组
     * @param[in] len 写入的长度
     * @return 返回实际的长度
     * @post 如果(m_position + len) > m_capacity 则 m_capacity扩容N个节点以容纳len长度
     */
    uint64_t getWriteBuffer(std::vector<iovec>& buffer, uint64_t len);

    size_t getSize() const {return m_writePosition;}

private:
    void addCapacity(size_t size);

    size_t getCapacity() const {return m_capacity - m_writePosition;}

private:
    size_t m_baseSize;
    size_t m_readPosition;
    size_t m_writePosition;
    size_t m_capacity;
    int8_t m_endian;
    Node* m_root;
    Node* m_readCur;
    Node* m_writeCur;



};

}













#endif